﻿using IR.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IR.Model.Models
{
    public class MNote
    {
        private int _noteID;
        private MIdea _idea;
        private MUser _user;
        private DateTime _dateCreated;
        private string _notes;

        #region ***Properties***
        public int NoteID
        {
            get { return _noteID; }
        }

        public MIdea Idea
        {
            get { return _idea; }
            set
            {
                if (value != null)
                    _idea = value;
            }
        }

        public MUser User
        {
            get { return _user; }
            set
            {
                if (value != null)
                    _user = value;
            }
        }

        public DateTime DateCreated
        {
            get { return _dateCreated; }
            set
            {
                if (value != null)
                    _dateCreated = value;
            }
        }

        public string Notes
        {
            get { return _notes; }
            set
            {
                if (value != null)
                    _notes = value;
            }
        }
        #endregion

        /// <summary>
        /// This will save the current Note (new or old)
        /// </summary>
        /// <param name="allowOverwrite">Allow updating old notes</param>
        /// <returns>True if saved</returns>
        public bool Save(bool allowOverwrite = false)
        {
            IREntities context = new IREntities();

            // Set values as these are needed either way
            note currentNote = new note
            {
                idea = _idea.IdeaID,
                user_created = _user.Username,
                date_created = _dateCreated,
                notes = _notes
            };

            // Check if new note
            note original = context.notes.Find(_noteID);

            if (original == null)
            {
                try
                {
                    context.notes.Add(currentNote);
                    return true;
                }
                catch
                {
                    return false;
                }
            }
            else if (allowOverwrite == true)
            {
                try
                {
                    context.Entry(original).CurrentValues.SetValues(currentNote);
                    return true;
                }
                catch
                {
                    return false;
                }
            }

            return false;
        }

        /// <summary>
        /// Loads and returns a note (Can be used to initialize)
        /// </summary>
        /// <param name="usernameToLoad">NoteID to look for</param>
        /// <returns>Null if failed</returns>
        public static MNote Load(int noteIDToLoad)
        {
            IREntities context = new IREntities();

            // Search for the note
            note original = context.notes.Find(noteIDToLoad);

            // If found load it
            if (original == null)
            {
                return null;
            }
            else
            {
                MNote currentNote = new MNote();

                currentNote._noteID = original.idnotes;
                currentNote._idea = MIdea.Load(original.idea);
                currentNote._user = MUser.Load(original.user_created);
                currentNote._dateCreated = original.date_created;
                currentNote._notes = original.notes;

                return currentNote;
            }
        }

        /// <summary>
        /// Gets all notes currently in the DB
        /// </summary>
        /// <returns>List of all notes</returns>
        private static List<MNote> GetAllNotes()
        {
            IREntities context = new IREntities();

            List<note> rowList = context.notes.Select(v => v).ToList();
            List<MNote> returnList = new List<MNote>(10);

            foreach (note row in rowList)
            {
                MNote currentNote = new MNote();

                currentNote._noteID = row.idnotes;
                currentNote._idea = MIdea.Load(row.idea);
                currentNote._user = MUser.Load(row.user_created);
                currentNote._dateCreated = row.date_created;
                currentNote._notes = row.notes;

                returnList.Add(currentNote);
            }

            return returnList;
        }

        /// <summary>
        /// Runs a query on the version table based on a Dictionary you pass in
        /// </summary>
        /// <param name="queries">Dictonary... key = column name, value = value in column</param>
        /// <returns>List of MNotes matching all params, all if null param</returns>
        public static List<MNote> QueryNotes(Dictionary<string, object> queries)
        {
            IREntities context = new IREntities();

            var listOfProperties = typeof(MNote).GetProperties().ToList();

            List<MNote> returnNotes = GetAllNotes();

            foreach (KeyValuePair<string, object> currentQuery in queries)
            {
                // Gets the current property (column) by stripping off the opening part that defines the namespace
                var currentProperty = listOfProperties
                    .Where(p => p.ToString().Split(' ').ElementAtOrDefault(1) == currentQuery.Key).FirstOrDefault();
                // Filters 'in' all rows that have the column value asked for
                //(so if multiple values are asked for it only returns rows with all values asked for)
                returnNotes = returnNotes.Where(v => currentProperty.GetValue(v).ToString() == currentQuery.Value.ToString()).ToList();
            }

            return returnNotes;
        }
    }
}
